主にLLVMを使用しています


概要

http://partake.in/events/9658f376-6ce3-4217-b392-b05d3de60021

昨日は @yusuke_kokubo さんでした。

りあじゅうばくはつしろ!



LLとかMLという語句がついてればOKだと思うので、


今回は

_人人人人人人人人人人_
> 突然のemscripten <
 ̄^Y^Y^Y^Y^Y^Y^Y^Y^ ̄


emscriptenとは

OCamlでJSやるのとかありますよね。 いいですよね!! JS書かずにすむとかGooooodです。

emscriptenは、

その辺の「こんな言語からJSが生成されるなんて!!」的な言語のお友達です。

こわくない。



Q.どこがMLだったりLLなのか


A.LLVMです。 JS生成にLLVMを使用しています。


emscriptenは、LLVMを使って、いろんな言語のコンパイル結果としてJSを吐き出します


毎回なぜかこの辺でドン引きされますが、

コワくない。


本体

githubにホストして開発されてる

https://github.com/kripken/emscripten/wiki



わかりやすい日本語での解説

Emscriptenの論文読んだ。Webの賢い選択。

http://akidev.hateblo.jp/entry/2012/04/12/233934



自分も5月くらいになんか書いてました。もう古い。

emscriptenを動かしてみる

http://sassembla.github.com/Public/12:05:21%2017-38-30/12:05:21%2017-38-30.html


補足

LLVMって?

コレ。 コンパイラみたいなものです。

http://llvm.org



やってみよう!

今回は、Objective-CのコードをJS化してみるよ!


といってもヘビー級だと絶対破滅するので、

軽めのをソースからJS化してみます。



脱線するけど。

本来の「言語をコンパイル可能な状況に持ち込む事で、出来るとうれしい事は何か」;


1.メッセージングの機構とか、JSでやるとクソみたいな事を、Cとかで書いてJSに持ち込む

2.人の手が絶対につけられないJSソースコードを吐く(マイナーチェンジや場当たりなど、変更可能性の更迭)

3.テストが容易


2.3が絶大なメリットだと思ってて、

変更可能性の無い = 人間が弄れない、なんだけど、

そういうソースコードでなにかをコントロールする世界にしていかないと、Webまわりはもうずっとこのままだと思う。


外部化のために、変更可能性をより上部に持っていく必要を感じているのです。



で、手順!


MacでClangをインストール

Xcodeから入れると、フレームワークとかのパス設定をはしょれて凄く楽です。

Xcode > Preferences > Downloads > 


最初llvm自体をDLして、ガチで挑んで死ぬかと思いました。


Windowsでも調べてみたら相ッ当なドMな方だとお見受けしますが、

何人か「環境作ってみたぜ!」な方々がいらっしゃいました。正直koeee。



Cの簡単なファイルを試しに一発ビルド

対象のファイルはこんな感じ。


test.c

#include <stdio.h>

int main()

{

    int i = 0;

for (i = 0; i < 99; i++) printf("hello, world %d\n", i);

    return 0;

}


適当な回数hello, world っていうプログラムです。


ビルド

llvmは、clangというフロントエンドツールを介してコントロールします。


ビルドコマンドは

clang test.c -v

スクリーンショット 2012-12-18 22.29.04.png

成果としてa.outができましたよっと。


スクリーンショット 2012-12-18 22.29.26.png



Obj-Cの簡単なファイルを試しに一発ビルド

対象のファイルはこんな感じ


test.m

#import <Foundation/Foundation.h>


@interface X : NSObject

@end


@implementation X

-(void)hello {

       printf("Hello\n");

}


@end


int main() {

X * obj = [[X alloc] init];

  [obj hello];

    return 0;

}


ビルド

clang  -fobjc-arc -framework Foundation test.m -o testObjC.out


出来上がったバイナリを実行すると、

スクリーンショット 2012-12-21 6.23.45.png





ビルドできる環境が整ったら、.ll/.bcファイルを出力

emscriptenに喰わせるため、LLVM IR(Intermediate Representation) = LLVM上でのコード中間表現 を生成する。



ちょっと脱線しつつ説明しておくと、


llvmは「ローレベルなバーチャルマシンで色んな事をする為のコンパイルの基盤」で、

その目的は

・言語をビルドする行為それ自体と、ビルドしたものが実際に動作するアーキテクチャを切り離す

・中間言語の時点で最適化を施す

というもの。超ザックリ。

で、.ll/.bcファイルは、その中間言語化された状態。optとかを使って最適化ができる。ここではやんないけど。

実行形式を引きずってない、意図だけのソース。

その辺をclangからつくる。



clang -O3 -emit-llvm test.m -c -o test.bc


こんなのが出来る。

スクリーンショット 2012-12-18 23.53.50.png



emscriptenのセットアップ

割愛。

参考になるステキな記事。

c/c++ -> javascript 変換compiler - emscripten を試す

http://d.hatena.ne.jp/end0tknr/20120714/1342233561



作成した中間言語をemsriptenでjs化

C言語版

./emscripten/emcc ソース.c

出力されるのが、.jsファイル。

-o 出力ファイル名 とかで調整も可能。



Cオリジナル

https://dl.dropbox.com/u/36583594/shared/test/test.c

js化したものをhtmlに入れたヤツ

https://dl.dropbox.com/u/36583594/shared/test/test.html

Cのprintfに対応して、プリント文が出てるぞ!! デバッガを見てね!

スクリーンショット 2012-12-19 0.34.15.png


Obj-C版

オリジナル

https://dl.dropbox.com/u/36583594/shared/test/test.m

★最新のemsだと、.llからの変換が駄目らしい!!!

調整中、、2012/12/18 23:57:43



明日は @kei10in さんです。


番外編失敗狂の詩

何手か、悪手っぽいものを試して失敗したのでメモまでに。


Obj-Cからc++とかに変換すればいいんじゃね?

clang -rewrite-objc .mファイルをcppファイルに変換できるので、それをビルドすれば、、!!という。

アイデア自体はまあ平和だったんですが、詰まったので方向転換しました。









以下メモ



emscripten側を弄る

・設定ファイルを更新

LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '/usr/bin/')



llvm-linkとllvm-arとoptとllvm-asとllvm-disと

llvm-nmを追加



で、


./emscripten/emcc /Users/sassembla/test/ems/test.m.cpp

(Emscripten: settings file has changed, clearing cache)

warning: LLVM version appears incorrect (seeing "Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)", expected "clang version 3.1")

(Emscripten: Running sanity checks)

/Users/sassembla/test/ems/test.m.cpp:69:9: warning: '__block' macro redefined

#define __block

        ^

<built-in>:20:9: note: previous definition is here

#define __block __attribute__((__blocks__(byref)))

        ^

/Users/sassembla/test/ems/test.m.cpp:73:10: fatal error: 

      'Foundation/Foundation.h' file not found

#include <Foundation/Foundation.h>

         ^

1 warning and 1 error generated.

emcc: compiler frontend failed to generate LLVM bitcode, halting


なので、

frameworkを読むように設定して、


./emscripten/emcc -framework /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h /Users/sassembla/test/ems/test.m.cpp -o a.out.js


おおーエラー無く出せた。

でもこれ何が出てるんだろう。。。



CPPがそのまま吐かれてた

グハー


ということで、このルートは無し。


再度チャレンジ


./emscripten/emcc -framework  /Users/sassembla/test/ems/test.m.cpp -o a.out.js


llvmが吐き出す中間成果物をもとに、emscriptenしてみる


llvm-dis

llvm-dis /Users/sassembla/Desktop/compile/test.bc